package cn.newtest.common.dbutils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Calendar;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.support.lob.LobHandler;

/**
 * 按照数据库特点和应用系统的特点来处理
 * 
 * @author WangChui(baiyibing@gmail.com)
 * @version 1.0 TODO
 * 
 */

public class OracleUtils implements DBUtils {
	private static final Log log = LogFactory.getLog(OracleUtils.class);
	private LobHandler lobHandler;

	/**
	 * Set the LobHandler to use for BLOB/CLOB access. Could use a
	 * DefaultLobHandler instance as default, but relies on a specified
	 * LobHandler here.
	 * 
	 * @see org.springframework.jdbc.support.lob.DefaultLobHandler
	 */
	public void setLobHandler(LobHandler lobHandler) {
		this.lobHandler = lobHandler;
	}

	public LobHandler getLobHandler() {
		return lobHandler;
	}

	public Object processColumn(ResultSet rs, int index, Class propType,
			int columnType) throws SQLException {
		// log.debug("propType="+propType+",columnType="+columnType);
		Object object = null;
		switch (columnType) {
		case Types.BIGINT:
			object = new Long(rs.getLong(index));
			break;
		case Types.BIT:
			object = new Boolean(rs.getBoolean(index));
			break;
		case Types.BLOB:
			log.debug("is BLOB");
			if (rs.getBlob(index) != null) { // 将Blob字段转换为字节数组
				// 块方法
				// object = lobHandler.getBlobAsBytes(rs, index);
				try {
					// 流方法
					ByteArrayOutputStream swapStream = null;
					BufferedInputStream is = null;
					swapStream = new ByteArrayOutputStream();
					is = new BufferedInputStream(lobHandler
							.getBlobAsBinaryStream(rs, index));
					byte[] b = new byte[1024];
					int count = b.length;
					int readCount = 0; // 已经成功读取的字节的个数
					while (readCount != -1 || readCount >= count) {
						readCount = is.read(b);
						swapStream.write(b, 0, readCount);
					}
					object = swapStream.toByteArray();
					swapStream.close();
					is.close();
				} catch (Exception e) {
					object = null;
				}
				// 方法三
				// try {
				// Blob blob = rs.getBlob(index);
				// byte[] bytes = blob.getBytes((long) 1, (int) blob.length());
				// object = bytes.toString();
				// } catch (Exception e) {
				// byte[] bytes = rs.getBytes(index);
				// object = bytes.toString();
				// }
			}
			break;
		case Types.CHAR:
			if (rs.getString(index) != null) {
				object = rs.getString(index);
			} else {
				object = new String("");
			}
			break;
		case Types.CLOB:
			log.debug("is CLOB");
			if (rs.getClob(index) != null) { // 将Clob字段转换为字符串
				try {
					// 块方法
					// object = lobHandler.getClobAsString(rs, index);

					// 流方法
					BufferedReader rd = new BufferedReader(lobHandler
							.getClobAsCharacterStream(rs, index));
					char[] c = new char[1024];
					int count = c.length;
					int readCount = 0; // 已经成功读取的字节的个数
					StringBuffer bf = new StringBuffer();
					while (readCount != -1 || readCount >= count) {
						// 如果读到了-1，或者 读出的数据少于buffer的尺寸，表示已经读完该批数据，不再循环读取数据了
						readCount = rd.read(c);
						for (int x = 0; x < readCount; x++) {
							bf.append(c[x]);
						}
					}
					object = bf.toString();
					rd.close();
				} catch (Exception e) {
					object = null;
				}

				// 方法三
				// Clob clob = rs.getClob(index);
				// Reader rd = clob.getCharacterStream();
				// char[] c = new char[(int) clob.length()];
				// rd.read(c);
				// StringBuffer bf = new StringBuffer();
				// for (int x = 0; x < c.length; x++) {
				// bf.append(c[x]);
				// }
				// object = bf.toString();
				// } catch (Exception e) {
				// byte[] bytes = rs.getBytes(index);
				// object = bytes.toString();
				// }
			}
			break;
		case Types.DATE:
			if (rs.getDate(index) != null) {
				object = getString(rs.getDate(index));
			}
			break;
		case Types.DECIMAL:
			if (rs.getBigDecimal(index) != null) {
				object = rs.getBigDecimal(index);
			} else {
				object = new java.math.BigDecimal(0);
			}
			object = getString(object);
			break;
		case Types.DOUBLE:
			object = new Double(rs.getDouble(index));
			break;
		case Types.FLOAT:
			object = new Float(rs.getFloat(index));
			break;
		case Types.INTEGER:
			object = new Integer(rs.getInt(index));
			break;
		case Types.LONGVARBINARY:
			if (rs.getBlob(index) != null) { // 将Blob字段转换为字节数组
				try {
					Blob blob = rs.getBlob(index);
					byte[] bytes = blob.getBytes((long) 1, (int) blob.length());
					object = bytes.toString();
				} catch (Exception e) {
					byte[] bytes = rs.getBytes(index);
					object = bytes.toString();
				}
			}
			break;
		case Types.LONGVARCHAR:
			if (rs.getString(index) != null) {
				object = rs.getString(index);
			} else {
				object = new String("");
			}
			break;
		case Types.NULL:
			object = new Object();
			break;
		case Types.NUMERIC:
			if (rs.getBigDecimal(index) != null) {
				object = rs.getBigDecimal(index);
			} else {
				object = new java.math.BigDecimal(0);
			}
			// object = getString(object);
			break;
		case Types.REAL:
			object = new Float(rs.getFloat(index));
			break;
		case Types.SMALLINT:
			object = new Integer(rs.getInt(index));
			break;
		case Types.TIME:
			if (rs.getTime(index) != null) {
				object = getString(rs.getTime(index));
			}
			break;
		case Types.TIMESTAMP:
			if (rs.getTimestamp(index) != null) {
				object = getString(rs.getTimestamp(index));
			}
			break;
		case Types.TINYINT:
			object = new Integer(rs.getInt(index));
			break;
		case Types.VARBINARY:
			if (rs.getBytes(index) != null) {
				object = rs.getBytes(index);
			}
			break;
		case Types.VARCHAR:
			if (rs.getString(index) != null) {
				object = rs.getString(index);
			} else {
				object = new String("");
			}
			break;
		default:
			if (rs.getObject(index) != null) {
				object = rs.getObject(index);
			}
		}
		return object;
	}

	static private String getString(Object obj) {
		String retStr = null;
		if (obj != null) {
			if (obj instanceof java.sql.Date) {
				java.sql.Date dateTemp = (java.sql.Date) obj;
				Calendar c = Calendar.getInstance();
				c.setTime(dateTemp);
				retStr = c.get(Calendar.YEAR) + "-"
						+ (c.get(Calendar.MONTH) + 1) + "-"
						+ c.get(Calendar.DAY_OF_MONTH);
			} else if (obj instanceof java.sql.Time) {
				java.sql.Date dateTemp = (java.sql.Date) obj;
				Calendar c = Calendar.getInstance();
				c.setTime(dateTemp);
				retStr = c.get(Calendar.YEAR) + "-"
						+ (c.get(Calendar.MONTH) + 1) + "-"
						+ c.get(Calendar.DAY_OF_MONTH);
			} else if (obj instanceof java.sql.Timestamp) {
				java.sql.Timestamp dateTemp = (java.sql.Timestamp) obj;
				Calendar c = Calendar.getInstance();
				c.setTime(dateTemp);
				retStr = c.get(Calendar.YEAR) + "-"
						+ (c.get(Calendar.MONTH) + 1) + "-"
						+ c.get(Calendar.DAY_OF_MONTH);
			} else if (obj instanceof java.math.BigDecimal) {
				java.math.BigDecimal big = (java.math.BigDecimal) obj;
				retStr = big.toString();
			} else {
				retStr = obj.toString();
			}
		}
		return retStr;
	}

}
